package com.fast.fastenjoy.fileplug.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.fast.fastenjoy.base.utils.StringExUtils;
import com.fast.fastenjoy.fileplug.domain.FileMd5Hex;
import com.fast.fastenjoy.fileplug.domain.UpgradeFile;
import com.fast.fastenjoy.fileplug.domain.UpgradeFileFileter;
import com.fast.fastenjoy.fileplug.exception.FileMd5HexException;

public class FilePlugUtils {

	public static boolean rename(String filePath, String newName){
		
		return rename(filePath, newName, false);
	}
	
	public static boolean rename(String filePath, String newName, boolean isCheckEndSuffix){
		
		return rename(new File(filePath), newName, isCheckEndSuffix);
	}
	
	public static boolean rename(File file, String newName, boolean isCheckEndSuffix){
		
		if(file == null || !file.exists() || StringUtils.isEmpty(newName)){
			return false;
		}
		
		String _oldName = file.getName();
		
		if(!StringUtils.equalsIgnoreCase(_oldName, newName)){
			
			String _oldpath = file.getAbsolutePath();
			String _newPath = StringUtils.EMPTY;
			
			int _oldNameLastIndexOf = _oldpath.lastIndexOf(_oldName);
			String _parentPath = _oldpath.substring(0, _oldNameLastIndexOf);
			
			if(isCheckEndSuffix){
				int _suffixIndex = _oldName.lastIndexOf(".");
				String _suffix = StringUtils.EMPTY;
				if(_suffixIndex > 0){
					_suffix = _oldName.substring(_suffixIndex);
				}
				_newPath = new StringBuffer(_parentPath).append(newName).append(_suffix).toString();
			}else{
				_newPath = new StringBuffer(_parentPath).append(newName).toString();
			}
			
			return file.renameTo(new File(_newPath));
		}
		
		return true;
	}
	
	/**
	 * 创建文件
	 * @param createFilePath 创建地址
	 * @param existsIsDelete 存在是否进行删除
	 * @return
	 */
	public static boolean createFile(String createFilePath, boolean existsIsDelete){
		
		if(StringUtils.isEmpty(createFilePath)){
			return Boolean.FALSE;
		}
		
		boolean isCreate = false;
		
		try{
			File f = new File(createFilePath);
			if(f.exists()){
				if(existsIsDelete){
					f.delete();
					f.createNewFile();
				}else{
					return false;
				}
			}else{
				f.createNewFile();
			}
			isCreate = true;
		}catch(Exception e){
		}
		
		return isCreate;
	}
	
	/**
	 * 创建文件夹
	 * @param createFilePath 创建地址
	 * @param existsIsDelete 存在是否进行删除
	 * @return
	 */
	public static boolean createDirectory(String createDirectoryPath, boolean existsIsDelete){
		
		boolean isCreate = false;
		
		try{
			File f = new File(createDirectoryPath);
			if(f.exists()){
				if(existsIsDelete){
					f.delete();
					f.mkdir();
				}else{
					return false;
				}
			}else{
				f.mkdir();
			}
			isCreate = true;
		}catch(Exception e){
		}
		
		return isCreate;
	}
	
	/**
	 * 获取版本差异列表
	 * @param _new
	 * @param _old
	 * @return
	 */
	public static Map<String, UpgradeFile> getDiffFileMd5Hex(Map<String, FileMd5Hex> _new, 
			Map<String, FileMd5Hex> _old){
		
		return getDiffFileMd5Hex(_new, _old, null);
	}
	
	/**
	 * 获取版本差异列表
	 * @param _new
	 * @param _old
	 * @param filter
	 * @return
	 */
	public static Map<String, UpgradeFile> getDiffFileMd5Hex(Map<String, FileMd5Hex> _new, 
			Map<String, FileMd5Hex> _old, UpgradeFileFileter filter){
		
		Map<String, UpgradeFile> result = new HashMap<String, UpgradeFile>();
		
		// 1.新版本为空
		if(_new == null){
			
		}
		
		// 2.旧版本为空则全量升级
		else if(_old == null){
			Iterator<String> iterator = _new.keySet().iterator();
			while(iterator.hasNext()){
				String key = iterator.next();
				UpgradeFile upgradeFile = UpgradeFile.buildUpgradeFile(key, _new.get(key), UpgradeFile.UP_TYPE_ADD);
				putUpgradeFile(upgradeFile, result, filter);
			}
		}
		
		// 3.比对升级
		else{
			
			Iterator<String> iterator = _new.keySet().iterator();
			List<String> _oldProcessMarkKeyList = new ArrayList<String>();
			while(iterator.hasNext()){
				
				String key = iterator.next();
				FileMd5Hex _newfileMd5Hex = _new.get(key);
				
				if(_newfileMd5Hex == null){
					continue;
				}
				
				if(_old.containsKey(key)){
					
					// 添加已处理标识
					_oldProcessMarkKeyList.add(key);
					
					FileMd5Hex _oldfileMd5Hex = _old.get(key);
					
					// 相同
					if(StringUtils.endsWithIgnoreCase(_newfileMd5Hex.getMd5(), _oldfileMd5Hex.getMd5())){
						continue;
					}
					
					// 发生变更
					else{
						UpgradeFile upgradeFile = UpgradeFile.buildUpgradeFile(key, _newfileMd5Hex, UpgradeFile.UP_TYPE_UPDATE);
						putUpgradeFile(upgradeFile, result, filter);
					}
				}
				
				// 旧版本不存在，则为新增
				else{
					UpgradeFile upgradeFile = UpgradeFile.buildUpgradeFile(key, _newfileMd5Hex, UpgradeFile.UP_TYPE_ADD);
					putUpgradeFile(upgradeFile, result, filter);
				}
			}
			
			// 旧版本未处理过则视为需要删除操作
			iterator = _old.keySet().iterator();
			while(iterator.hasNext()){
				String _oldKey = iterator.next();
				if(_oldProcessMarkKeyList.contains(_oldKey)){
					continue;
				}
				UpgradeFile upgradeFile = UpgradeFile.buildUpgradeFile(_oldKey, _old.get(_oldKey), UpgradeFile.UP_TYPE_REMOVE);
				putUpgradeFile(upgradeFile, result, filter);
			}
		}
		
		return result;
	}
	
	/**
	 * 计算过滤升级的文件
	 * @param upgradeFile
	 * @param upgradeFileMap
	 * @param filter
	 */
	private static void putUpgradeFile(UpgradeFile upgradeFile, Map<String, UpgradeFile> upgradeFileMap, 
			UpgradeFileFileter filter){
		
		if(upgradeFile == null || upgradeFileMap == null){
			return;
		}
		
		boolean isAdd = filter == null || !filter.filter(upgradeFile);
		
		if(isAdd){
			upgradeFileMap.put(upgradeFile.getUrl(), upgradeFile);
		}
	}
	
	/**
	 * 文件夹复制
	 * @param srcDirPath
	 * @param destDirPath
	 */
	public static void copyDirectory(String srcDirPath, String destDirPath){
		
		if(StringUtils.isEmpty(srcDirPath) || StringUtils.isEmpty(destDirPath)){
			return;
		}
		
		copyDirectory(new File(srcDirPath), new File(destDirPath));
	}
	
	/**
	 * 文件夹复制
	 * @param srcDir
	 * @param destDir
	 */
	public static void copyDirectory(File srcDir, File destDir){
		
		if(srcDir == null || destDir == null 
				|| !srcDir.exists() || !srcDir.isDirectory()
				|| destDir.isFile()){
			return;
		}
		
		try{
			
			if(!destDir.exists()){
				destDir.mkdir();
			}
			
			File[] listFiles = srcDir.listFiles();
			
			if(listFiles != null){
				for(File f : listFiles){
					try{
						System.out.println(f.getCanonicalPath());
						copyFile(f, srcDir.getAbsolutePath(), destDir);
					}catch(Throwable _e){
						System.out.println("复制文件" + f.getAbsolutePath() + "出错，message:" + _e.getMessage());
					}
				}
			}
			
		}catch(Throwable e){
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 复制文件
	 * @param file
	 * @param withPath
	 * @param destDir
	 * @throws Throwable
	 */
	private static void copyFile(File file, String withPath, File destDir) throws Throwable{
		
		String d_absolutePath = destDir.getAbsolutePath();
		String relativePath = StringExUtils.replace(file.getAbsolutePath(), withPath, StringExUtils.EMPTY);
		String newFilePath = StringExUtils.append(d_absolutePath, relativePath);
		File newFile = new File(newFilePath);
		
		if(file.isDirectory()){
			newFile.mkdir();
			File[] listFiles = file.listFiles();
			if(listFiles != null){
				for(File f : listFiles){
					copyFile(f, withPath, destDir);
				}
			}
		}else{
			FileUtils.copyFile(file, newFile);
		}
	}
	
	/**
	 * json转换为Map<String, FileMd5Hex>
	 * @param jsonText
	 * @return
	 */
	public static Map<String, FileMd5Hex> buildCheckList(String jsonText){
		
		Map<String, FileMd5Hex> tempMap = new HashMap<String, FileMd5Hex>();
		
		try{
			
			JSONObject json = JSONObject.parseObject(jsonText);
			
			Iterator<String> iterator = json.keySet().iterator();
			
			while(iterator.hasNext()){
				try{
					String key = iterator.next();
					JSONObject jsonObject = json.getJSONObject(key);
					tempMap.put(key, JSONObject.parseObject(jsonObject.toJSONString(), FileMd5Hex.class));
				}catch(Exception _e){
				}
			}
			
		}catch(Exception e){
		}
		
		return tempMap;
	}
	
	/**
	 * 获取文件MD5列表
	 * @param baseFilePath
	 */
	public static Map<String, FileMd5Hex> getFileMd5Hex(String baseFilePath){
		
		return getFileMd5Hex(new File(baseFilePath));
	}
	
	/**
	 * 获取文件MD5列表
	 * @param baseFile
	 * @return
	 */
	public static Map<String, FileMd5Hex> getFileMd5Hex(File baseFile){
		
		Map<String, FileMd5Hex> tempMap = new HashMap<String, FileMd5Hex>();
		
		if(baseFile != null){
			String basePath = baseFile.getAbsolutePath();
			_getFileMd5HexOfDirectory(basePath, baseFile, tempMap);
		}
		
		return tempMap;
	}
	
	/**
	 * 获取文件MD5列表
	 * @param baseFilePath
	 */
	public static void _getFileMd5HexOfZip(String basePath, File baseFile, Map<String, FileMd5Hex> fileMd5HexMap){
		
	}
	
	/**
	 * 构造文件目录MD5值列表，包含所有子目录
	 * 
	 * @param baseFile
	 * @param fileMd5HexMap
	 */
	private static void _getFileMd5HexOfDirectory(String basePath, File baseFile, Map<String, FileMd5Hex> fileMd5HexMap){
		
		if(baseFile == null || fileMd5HexMap == null){
			return;
		}
		
		if(baseFile.isFile()){
			try {
				
				String path = baseFile.getAbsolutePath();
				
				String fileMd5HexKey = path.replace(basePath, StringUtils.EMPTY);
				
				if(StringUtils.isEmpty(fileMd5HexKey)){
					fileMd5HexKey = basePath;
				}
				
				fileMd5HexMap.put(fileMd5HexKey, new FileMd5Hex(baseFile));
				
			} catch (FileMd5HexException e) {
				e.printStackTrace();
			}
		}else{
			File[] listFiles = baseFile.listFiles();
			if(listFiles != null){
				for(File f : listFiles){
					_getFileMd5HexOfDirectory(basePath, f, fileMd5HexMap);
				}
			}
		}
	}
	
	/**
	 * 获取文件MD5值
	 * @param f
	 */
	public static void getFileMd5AndSize(FileMd5Hex fmh){
		
		File f = fmh.getFile();
		
		if(f != null && f.isFile()){
			FileInputStream fileInputStream = null;
			try {
				fileInputStream = new FileInputStream(f);
				fmh.setSize(fileInputStream.available());
				fmh.setMd5(DigestUtils.md5Hex(fileInputStream));
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				if(fileInputStream != null){
					try {
						fileInputStream.close();
					} catch (IOException e) {
					}
				}
			}
		}
	}
	
	/**
	 * 获取文件MD5值
	 * @param f
	 */
	public static String getFileMd5(File f){
		
		String md5 = null;
		
		if(f != null && f.isFile()){
			FileInputStream fileInputStream = null;
			try {
				fileInputStream = new FileInputStream(f);
				md5 = DigestUtils.md5Hex(fileInputStream);
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				if(fileInputStream != null){
					try {
						fileInputStream.close();
					} catch (IOException e) {
					}
				}
			}
		}
		
		return md5;
	}
	
}
